package com.three.iot.channel.impl.aliyun;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.iot.model.v20180120.*;
import com.github.pagehelper.Page;
import com.three.iot.channel.api.DeviceChannelService;
import com.three.iot.channel.po.*;
import com.three.iot.commons.enums.IotDeviceStatusEnum;
import com.three.iot.commons.enums.Result;
import com.three.iot.commons.enums.ResultCode;
import com.three.iot.commons.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author luiz
 * @Title: DeviceChannelServiceAliyun
 * @ProjectName iot-server
 * @Description: TODO
 * @date 2019-05-07 13:36
 */
@Service
@Slf4j
public class DeviceChannelServiceAliyun extends AbstractChannelServiceAliyun implements DeviceChannelService {


    @Override
    public Result<Page<DeviceRespPo>> findDeviceList(DeviceCondPo deviceCondPo) {
        QueryDeviceRequest request = new QueryDeviceRequest();
        request.setProductKey(deviceCondPo.getProductKey());
        request.setCurrentPage(deviceCondPo.getPageNum());
        request.setPageSize(deviceCondPo.getPageSize());
        try {
            log.debug("【阿里云】查询设备列表请求参数:{}", JSONObject.toJSONString(request));
            QueryDeviceResponse response = client.getAcsResponse(request);
            log.debug("【阿里云】查询设备列表响应数据:{}", JSONObject.toJSONString(response));
            if (response.getSuccess()) {
                Page<DeviceRespPo> deviceRespPoPage = new Page<DeviceRespPo>();
                deviceRespPoPage.setPages(response.getPageCount());
                deviceRespPoPage.setPageNum(deviceCondPo.getPageNum());
                deviceRespPoPage.setPageSize(response.getPageSize());
                deviceRespPoPage.setTotal(response.getTotal());
                List<QueryDeviceResponse.DeviceInfo> productInfoList = response.getData();
                for (QueryDeviceResponse.DeviceInfo deviceInfo : productInfoList) {
                    DeviceRespPo deviceRespPo = new DeviceRespPo();
                    BeanUtils.copyProperties(deviceInfo, deviceRespPo);
                    deviceRespPoPage.add(deviceRespPo);
                }
                return Result.newSuccess(deviceRespPoPage);
            }
            return Result.newError(ResultCode.CHANNEL_ERROR.getCode(), response.getErrorMessage());
        } catch (ServerException e) {
            log.error("【阿里云】查询设备服务端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        } catch (ClientException e) {
            log.error("【阿里云】查询设备客户端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        }
    }

    @Override
    public Result<DeviceDetailRespPo> findDeviceByCond(DeviceCondPo deviceCondPo) {
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotId(deviceCondPo.getDeviceId());
        request.setProductKey(deviceCondPo.getProductKey());
        request.setDeviceName(deviceCondPo.getDeviceName());
        return findDeviceById(request);
    }

    @Override
    public Result<DeviceDetailRespPo> findDeviceByNo(String iotNo) {
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotId(iotNo);
        return findDeviceById(request);
    }


    public Result<DeviceDetailRespPo> findDeviceById(QueryDeviceDetailRequest request) {
        try {
            log.debug("【阿里云】查询设备详情请求参数:{}", JSONObject.toJSONString(request));
            QueryDeviceDetailResponse response = client.getAcsResponse(request);
            log.debug("【阿里云】查询设备详情响应数据:{}", JSONObject.toJSONString(response));
            if (response.getSuccess()) {
                QueryDeviceDetailResponse.Data deviceDetailData = response.getData();
                DeviceDetailRespPo deviceDetailRespPo = new DeviceDetailRespPo();
                BeanUtils.copyProperties(deviceDetailData, deviceDetailRespPo);
                deviceDetailRespPo.setDeviceStatus(deviceDetailData.getStatus());
                deviceDetailRespPo.setDeviceStatusName(IotDeviceStatusEnum.getNameByCode(deviceDetailData.getStatus()));
                return Result.newSuccess(deviceDetailRespPo);
            }
            return Result.newError(ResultCode.CHANNEL_ERROR.getCode(), response.getErrorMessage());
        } catch (ServerException e) {
            log.error("【阿里云】查询设备详情服务端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        } catch (ClientException e) {
            log.error("【阿里云】查询设备详情客户端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        }
    }

    /**
     * 下发命令控制开关
     *
     * @return
     */
    @Override
    public Result setDeviceProperty(DevicePropertyPo devicePropertyPo) {
        SetDevicePropertyRequest request = new SetDevicePropertyRequest();
        request.setActionName("SetDeviceProperty");
        request.setIotId(devicePropertyPo.getIotId());
        JSONObject itemJson = devicePropertyPo.getParamObj();
        request.setItems(itemJson.toJSONString());
        try {
            log.debug("【阿里云】控制设备属性请求参数:{}", JSONObject.toJSONString(request));
            SetDevicePropertyResponse response = client.getAcsResponse(request);
            log.debug("【阿里云】控制设备属性响应数据:{}", JSONObject.toJSONString(response));
            if (response.getSuccess()) {
                SetDevicePropertyResponse.Data devicePropertyRespData = response.getData();
                String messageId = devicePropertyRespData.getMessageId();
                return Result.newSuccess(messageId);
            }
            return Result.newError(ResultCode.CHANNEL_ERROR.getCode(), response.getErrorMessage());
        } catch (ServerException e) {
            log.error("【阿里云】控制设备属性服务端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        } catch (ClientException e) {
            log.error("【阿里云】控制设备属性客户端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        }
    }

    /**
     * 查询该设备的所有属性
     *
     * @param devicePropertyPo
     * @return
     */
    @Override
    public Result<List<PropertyRespPo>> findDevicePropertys(DevicePropertyPo devicePropertyPo) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setIotId(devicePropertyPo.getIotId());
        request.setProductKey(devicePropertyPo.getProductKey());
        request.setDeviceName(devicePropertyPo.getDeviceName());
        return findDeviePropertys(request);
    }

    @Override
    public Result<List<PropertyRespPo>> findDevicePropertysByNo(String iotNo) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setIotId(iotNo);
        return findDeviePropertys(request);
    }

    Result<List<PropertyRespPo>>  findDeviePropertys(QueryDevicePropertyStatusRequest request){
        try {
            log.debug("【阿里云】查询设备属性请求参数:{}", JSONObject.toJSONString(request));
            QueryDevicePropertyStatusResponse response = client.getAcsResponse(request);
            log.debug("【阿里云】查询设备属性响应数据:{}", JSONObject.toJSONString(response));
            if (response.getSuccess()) {
                List<QueryDevicePropertyStatusResponse.Data.PropertyStatusInfo> props = response.getData().getList();
                List<PropertyRespPo> propertyRespPos=new ArrayList<>();
                for(QueryDevicePropertyStatusResponse.Data.PropertyStatusInfo propertyStatusInfo : props){
                    PropertyRespPo propertyRespPo=new PropertyRespPo();
                    BeanUtils.copyProperties(propertyStatusInfo,propertyRespPo);
                    propertyRespPos.add(propertyRespPo);
                }
                return Result.newSuccess(propertyRespPos);
            }
            return Result.newError(ResultCode.CHANNEL_ERROR.getCode(), response.getErrorMessage());
        } catch (ServerException e) {
            log.error("【阿里云】查询设备属性服务端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        } catch (ClientException e) {
            log.error("【阿里云】查询设备属性客户端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        }
    }

    /**
     * 查询标签数据
     *
     * @param devicePropertyDataPo
     * @return
     */
    @Override
    public Result<DeviceSinglePropertyDataRespPo> findDevicePropertyData(DevicePropertyDataPo devicePropertyDataPo) {
        QueryDevicePropertyDataRequest queryDevicePropertyData = new QueryDevicePropertyDataRequest();
        queryDevicePropertyData.setIotId(devicePropertyDataPo.getIotId());
        queryDevicePropertyData.setIdentifier(devicePropertyDataPo.getIdentifier());
        queryDevicePropertyData.setStartTime(devicePropertyDataPo.getStartTime());
        queryDevicePropertyData.setEndTime(devicePropertyDataPo.getEndTime());
        queryDevicePropertyData.setPageSize(devicePropertyDataPo.getPageSize());
        queryDevicePropertyData.setAsc(devicePropertyDataPo.getAsc());
        try {
            log.debug("【阿里云】查询标签数据请求参数:{}", JSONObject.toJSONString(queryDevicePropertyData));
            QueryDevicePropertyDataResponse response = client.getAcsResponse(queryDevicePropertyData);
            log.debug("【阿里云】查询标签数据响应数据:{}", JSONObject.toJSONString(response));
            if (response.getSuccess()) {
                QueryDevicePropertyDataResponse.Data devicePropertyRespData = response.getData();
                List<QueryDevicePropertyDataResponse.Data.PropertyInfo> propertyInfoList = devicePropertyRespData.getList();
                List<PropertyDataDetailRespPo> propertyDataDetailRespPos = new ArrayList<PropertyDataDetailRespPo>();
                if (propertyInfoList != null && propertyInfoList.size() >= 1) {
                    for (QueryDevicePropertyDataResponse.Data.PropertyInfo sinlgePropertyInfo : propertyInfoList) {
                        PropertyDataDetailRespPo propertyDataDetailRespPo = new PropertyDataDetailRespPo();
                        String timeLong = DateUtil.formatDateTime(Long.valueOf(sinlgePropertyInfo.getTime()));
                        propertyDataDetailRespPo.setTime(timeLong);
                        propertyDataDetailRespPo.setValue(sinlgePropertyInfo.getValue());
                        propertyDataDetailRespPos.add(propertyDataDetailRespPo);
                    }
                }
                PropertyDataRespPo propertyDataRespPo=new PropertyDataRespPo();
                propertyDataRespPo.setIdentifier(devicePropertyDataPo.getIdentifier());
                propertyDataRespPo.setPropertyDataDetailRespPoList(propertyDataDetailRespPos);
                DeviceSinglePropertyDataRespPo deviceSinglePropertyDataRespPo = new DeviceSinglePropertyDataRespPo();
                deviceSinglePropertyDataRespPo.setNextValid(devicePropertyRespData.getNextValid());
                deviceSinglePropertyDataRespPo.setNextTime(devicePropertyRespData.getNextTime());
                deviceSinglePropertyDataRespPo.setIotId(devicePropertyDataPo.getIotId());
                deviceSinglePropertyDataRespPo.setPropertyDataRespPo(propertyDataRespPo);
                return Result.newSuccess(deviceSinglePropertyDataRespPo);
            }
            return Result.newError(ResultCode.CHANNEL_ERROR.getCode(), response.getErrorMessage());
        } catch (ServerException e) {
            log.error("【阿里云】查询标签数据服务端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        } catch (ClientException e) {
            log.error("【阿里云】查询标签数据客户端异常!{}", e);
            return Result.newError(ResultCode.FAIL);
        }
    }

    /**
     * 批量查询属性数据
     * 阿里云平台属性数目限制在10个以内
     * @param devicePropertysDataPo
     * @return
     */
    @Override
    public Result<DeviceMultiPropertyDataRespPo> findDevicePropertysData(DevicePropertysDataPo devicePropertysDataPo) {


        List<String> identLists = devicePropertysDataPo.getIdentifiers();
        // 阿里云平台属性数目限制在10个以内
        int limitNum=10;
        log.debug("totalSize:{}",identLists.size());
        if(identLists!=null && identLists.size()>=1){
            int totalLen=identLists.size();
            int countNum=totalLen/limitNum;
            List<QueryDevicePropertiesDataResponse.PropertyDataInfo> totalPropertyDataInfos=new ArrayList<>();
            DeviceMultiPropertyDataRespPo deviceMultiPropertyDataRespPo = new DeviceMultiPropertyDataRespPo();
            deviceMultiPropertyDataRespPo.setIotId(devicePropertysDataPo.getIotId());
            for(int i=0;i<=countNum;i++){
                int starIndex=i*limitNum;
                int endIndex=(i+1)*limitNum;
                if(i==countNum){
                    int remainNum=totalLen%limitNum;
                    if(totalLen%limitNum!=0){
                        endIndex=starIndex+remainNum;
                    }else {
                        break;
                    }
                }
                List<String> subList=identLists.subList(starIndex,endIndex);
                QueryDevicePropertiesDataRequest query = new QueryDevicePropertiesDataRequest();
                query.setIotId(devicePropertysDataPo.getIotId());
                query.setDeviceName(devicePropertysDataPo.getDeviceName());
                query.setProductKey(devicePropertysDataPo.getProductKey());
                query.setStartTime(devicePropertysDataPo.getStartTime());
                query.setEndTime(devicePropertysDataPo.getEndTime());
                if(devicePropertysDataPo.getAsc()==0){
                    query.setStartTime(devicePropertysDataPo.getEndTime());
                    query.setEndTime(devicePropertysDataPo.getStartTime());
                }
                query.setPageSize(devicePropertysDataPo.getPageSize());
                query.setAsc(devicePropertysDataPo.getAsc());
                // 阿里云平台属性数目限制在10个以内
                query.setIdentifiers(subList);
                log.debug("第{}次查询属性数据,startIndex:{},endIndex:{}:subList:{}",i+1,starIndex,endIndex,subList);
                QueryDevicePropertiesDataResponse  response= processSingleWhile(query);
                if(response!=null){
                    deviceMultiPropertyDataRespPo.setNextValid(response.getNextValid());
                    deviceMultiPropertyDataRespPo.setNextTime(response.getNextTime());
                    List<QueryDevicePropertiesDataResponse.PropertyDataInfo> PropertyDataInfos =response.getPropertyDataInfos();
                    totalPropertyDataInfos.addAll(PropertyDataInfos);
                }
            }
            //汇总后返回
            List<PropertyDataRespPo> propertyRespPos =buildPo(totalPropertyDataInfos);
            deviceMultiPropertyDataRespPo.setPropertyRespPoList(propertyRespPos);
            return Result.newSuccess(deviceMultiPropertyDataRespPo);
        }
        return Result.newError(ResultCode.COMMON_DATA_NOT_EXISTS);
    }

    private  QueryDevicePropertiesDataResponse processSingleWhile(QueryDevicePropertiesDataRequest query ) {
        try {
            log.debug("【阿里云】查询标签List数据请求参数:{}", JSONObject.toJSONString(query));
            QueryDevicePropertiesDataResponse response = client.getAcsResponse(query);
            log.debug("【阿里云】查询标签List数据响应数据:{}", JSONObject.toJSONString(response));
            if (response.getSuccess()) {
                return response;
            }
        } catch (ServerException e) {
            log.error("【阿里云】查询标签List数据服务端异常!{}", e);
            return null;
        } catch (ClientException e) {
            log.error("【阿里云】查询标签List数据客户端异常!{}", e);
            return null;
        }
        return null;
    }

    private List<PropertyDataRespPo> buildPo( List<QueryDevicePropertiesDataResponse.PropertyDataInfo> PropertyDataInfos) {
        List<PropertyDataRespPo> propertyRespPos = new ArrayList<>();
        if (PropertyDataInfos != null && PropertyDataInfos.size() >= 1) {
            for (QueryDevicePropertiesDataResponse.PropertyDataInfo propertyInfo : PropertyDataInfos) {
                PropertyDataRespPo propertyRespPo = new PropertyDataRespPo();
                propertyRespPo.setIdentifier(propertyInfo.getIdentifier());
                List<QueryDevicePropertiesDataResponse.PropertyDataInfo.PropertyInfo> propertyDataInfos=propertyInfo.getList();
                List<PropertyDataDetailRespPo> propertyDataDetailRespPos=new ArrayList<>();
                for(QueryDevicePropertiesDataResponse.PropertyDataInfo.PropertyInfo propertyDataInfo:propertyDataInfos){
                    PropertyDataDetailRespPo propertyDataDetailRespPo=new PropertyDataDetailRespPo();
                    String timeLong = DateUtil.formatDateTime(Long.valueOf(propertyDataInfo.getTime()));
                    propertyDataDetailRespPo.setTime(timeLong);
                    propertyDataDetailRespPo.setValue(propertyDataInfo.getValue());
                    propertyDataDetailRespPos.add(propertyDataDetailRespPo);
                }
                propertyRespPo.setPropertyDataDetailRespPoList(propertyDataDetailRespPos);
                propertyRespPos.add(propertyRespPo);
            }
        }
        return  propertyRespPos;
    }


}
